using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;
using System.Reflection;

using System.Windows.Forms;
using System.Data;
using AMStudio.Script;

namespace IPTE.Manager
{
    public partial class IOAssign
    {
        private static void InitScanPorts(RefrenceTagGroupCreator myClass)
        {
            if (IOConfig.ScanPorts == null)
            {
                return;
            }
            for (int i = 0; i < IOConfig.ScanPorts.Rows.Count; i++)
            {
                DataRow row = IOConfig.ScanPorts.Rows[i];
                if (string.IsNullOrEmpty(row[0].ToString()))
                    continue;
                try
                {
                    string name = row["Name"].ToString();
                    string modName = row["ModName"].ToString();
                    int startaddr = int.Parse(row["StartAddr"].ToString());
                    int cnt = int.Parse(row["Num"].ToString());
                    int id = int.Parse(row["Modules"].ToString());
                    string device = row["Device"].ToString();
                    int index = int.Parse(row["Index"].ToString());
                    string dir = row["Direction"].ToString().ToUpper();
                    string datatype = row["DataType"].ToString().ToUpper();
                    string readMode = row["ReadMode"].ToString();
                    int plc = int.Parse(row["PLC"].ToString());

                    PLC_IO_Flag area;
                    switch (device)
                    {
                        case "D":
                            area = PLC_IO_Flag.DM;
                            break;
                        case "H":
                            area = PLC_IO_Flag.H;
                            break;
                        case "E":
                            area = PLC_IO_Flag.E;
                            break;
                        case "W":
                            area = PLC_IO_Flag.W;
                            break;
                        case "C":
                            area = PLC_IO_Flag.CIO;
                            break;
                        default:
                            area = PLC_IO_Flag.CIO;
                            break;
                    }

                    PLC_Action_Flag act;
                    switch (dir)
                    {
                        case "BOTH":
                            act = PLC_Action_Flag.Both;
                            break;
                        case "OUT":
                            act = PLC_Action_Flag.Write;
                            break;
                        case "IN":
                        default:
                            act = PLC_Action_Flag.Read;
                            break;
                    }

                    PLC_IO_DATA_TYPE io_dat;
                    PLC_Cell cell;
                    switch (datatype)
                    {
                        case "BIT":
                            io_dat = PLC_IO_DATA_TYPE.Bit;
                            cell = new PLCBoolCell(name, modName, startaddr, index, cnt, act, area, io_dat, id, readMode, plc);
                            break;
                        case "WORD":
                        default:
                            io_dat = PLC_IO_DATA_TYPE.Word;
                            if (cnt == 1)
                            {
                                cell = new PLCIntCell(name, modName, startaddr, index, cnt, act, area, io_dat, id, readMode, plc);
                            }
                            else
                            {
                                cell = new PLCIntArrayCell(name, modName, startaddr, index, cnt, act, area, io_dat, id, readMode, plc);
                            }
                            break;
                    }

                    plcIO.Add(name, cell);
                    AddScanPortsProperty(myClass, name, cell);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(row["Name"].ToString() + ex.Message);
                }
            }
        }

        private static void InitPCICardIO(RefrenceTagGroupCreator myClass)
        {
            if (IOConfig.PCICardIO == null)
            {
                return;
            }
            for (int i = 0; i < IOConfig.PCICardIO.Rows.Count; i++)
            {
                DataRow row = IOConfig.PCICardIO.Rows[i];
                if (string.IsNullOrEmpty(row[0].ToString()))
                    continue;
                try
                {
                    string name = row["Name"].ToString();
                    string modName = row["ModName"].ToString();
                    int port = int.Parse(row["Port"].ToString());
                    int cnt = int.Parse(row["Num"].ToString());
                    int index = int.Parse(row["Index"].ToString());
                    string readMode = row["ReadMode"].ToString();
                    int card = int.Parse(row["Hardware"].ToString());
                    string comments = row["Hardware"].ToString();


                    string dir = row["Direction"].ToString().ToUpper();
                    string datatype = row["DataType"].ToString().ToUpper();

                    PCICard_PORT_TYPE pciPortType;
                    switch (dir)
                    {
                        case "BOTH":
                            pciPortType = PCICard_PORT_TYPE.Both;
                            break;
                        case "OUTPUT":
                            pciPortType = PCICard_PORT_TYPE.Output;
                            break;
                        case "INPUT":
                        default:
                            pciPortType = PCICard_PORT_TYPE.Input;
                            break;
                    }

                    PCICard_DATA_TYPE io_dat;
                    PCICardDIO cell;
                    switch (datatype)
                    {
                        case "BIT":
                            io_dat = PCICard_DATA_TYPE.Bit;
                            cell = new PCICardBoolCell(name,modName, port, index, cnt, pciPortType, io_dat, card, readMode, comments);
                            break;
                        case "WORD":
                        default:
                            io_dat = PCICard_DATA_TYPE.Byte;
                            if (cnt == 1)
                            {
                                cell = new PCICardByteCell(name, modName, port, index, cnt, pciPortType, io_dat, card, readMode, comments);
                            }
                            else
                            {
                                cell = new PCICardByteArrayCell(name, modName, port, index, cnt, pciPortType, io_dat, card, readMode, comments);
                            }
                            break;
                    }

                    pciCardIO.Add(name, cell);
                    AddPCICardIOProperty(myClass, name, cell);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(row["Name"].ToString() + ex.Message);
                }
            }
        }
        private static void InitPCICardIO()
        {
            if (IOConfig.PCICardIO == null)
            {
                return;
            }
            for (int i = 0; i < IOConfig.PCICardIO.Rows.Count; i++)
            {
                DataRow row = IOConfig.PCICardIO.Rows[i];
                if (string.IsNullOrEmpty(row[0].ToString()))
                    continue;
                try
                {
                    string name = row["Name"].ToString();
                    string modName = row["ModName"].ToString();
                    int port = int.Parse(row["Port"].ToString());
                    int cnt = int.Parse(row["Num"].ToString());
                    int index = int.Parse(row["Index"].ToString());
                    string readMode = row["ReadMode"].ToString();
                    int card = int.Parse(row["Hardware"].ToString());
                    string comments = row["Hardware"].ToString();


                    string dir = row["Direction"].ToString().ToUpper();
                    string datatype = row["DataType"].ToString().ToUpper();

                    PCICard_PORT_TYPE pciPortType;
                    switch (dir)
                    {
                        case "BOTH":
                            pciPortType = PCICard_PORT_TYPE.Both;
                            break;
                        case "OUTPUT":
                            pciPortType = PCICard_PORT_TYPE.Output;
                            break;
                        case "INPUT":
                        default:
                            pciPortType = PCICard_PORT_TYPE.Input;
                            break;
                    }

                    PCICard_DATA_TYPE io_dat;
                    PCICardDIO cell;
                    switch (datatype)
                    {
                        case "BIT":
                            io_dat = PCICard_DATA_TYPE.Bit;
                            cell = new PCICardBoolCell(name, modName, port, index, cnt, pciPortType, io_dat, card, readMode, comments);
                            break;
                        case "WORD":
                        default:
                            io_dat = PCICard_DATA_TYPE.Byte;
                            if (cnt == 1)
                            {
                                cell = new PCICardByteCell(name, modName, port, index, cnt, pciPortType, io_dat, card, readMode, comments);
                            }
                            else
                            {
                                cell = new PCICardByteArrayCell(name, modName, port, index, cnt, pciPortType, io_dat, card, readMode, comments);
                            }
                            break;
                    }

                    pciCardIO.Add(name, cell);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(row["Name"].ToString() + ex.Message);
                }
            }
        }
        private static void InitScanPorts()
        {
            if (IOConfig.ScanPorts == null)
            {
                return;
            }
            for (int i = 0; i < IOConfig.ScanPorts.Rows.Count; i++)
            {
                DataRow row = IOConfig.ScanPorts.Rows[i];
                if (string.IsNullOrEmpty(row[0].ToString()))
                    continue;
                try
                {
                    string name = row["Name"].ToString();
                    string modName = row["ModName"].ToString();
                    int startaddr = int.Parse(row["StartAddr"].ToString());
                    int cnt = int.Parse(row["Num"].ToString());
                    int id = int.Parse(row["Modules"].ToString());
                    string device = row["Device"].ToString();
                    int index = int.Parse(row["Index"].ToString());
                    string dir = row["Direction"].ToString().ToUpper();
                    string datatype = row["DataType"].ToString().ToUpper();
                    string readMode = row["ReadMode"].ToString();
                    int plc = int.Parse(row["PLC"].ToString());

                    PLC_IO_Flag area;
                    switch (device)
                    {
                        case "D":
                            area = PLC_IO_Flag.DM;
                            break;
                        case "H":
                            area = PLC_IO_Flag.H;
                            break;
                        case "E":
                            area = PLC_IO_Flag.E;
                            break;
                        case "W":
                            area = PLC_IO_Flag.W;
                            break;
                        case "C":
                            area = PLC_IO_Flag.CIO;
                            break;
                        default:
                            area = PLC_IO_Flag.CIO;
                            break;
                    }

                    PLC_Action_Flag act;
                    switch (dir)
                    {
                        case "BOTH":
                            act = PLC_Action_Flag.Both;
                            break;
                        case "OUT":
                            act = PLC_Action_Flag.Write;
                            break;
                        case "IN":
                        default:
                            act = PLC_Action_Flag.Read;
                            break;
                    }

                    PLC_IO_DATA_TYPE io_dat;
                    PLC_Cell cell;
                    switch (datatype)
                    {
                        case "BIT":
                            io_dat = PLC_IO_DATA_TYPE.Bit;
                            cell = new PLCBoolCell(name, modName, startaddr, index, cnt, act, area, io_dat, id, readMode, plc);
                            break;
                        case "WORD":
                        default:
                            io_dat = PLC_IO_DATA_TYPE.Word;
                            if (cnt == 1)
                            {
                                cell = new PLCIntCell(name, modName, startaddr, index, cnt, act, area, io_dat, id, readMode, plc);
                            }
                            else
                            {
                                cell = new PLCIntArrayCell(name, modName, startaddr, index, cnt, act, area, io_dat, id, readMode, plc);
                            }
                            break;
                    }

                    plcIO.Add(name, cell);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(row["Name"].ToString() + ex.Message);
                }
            }
        }
        private static void InitBits(string className)
        {
            if (IOConfig.Bits == null)
            {
                return;
            }
            for (int i = 0; i < IOConfig.Bits.Rows.Count; i++)
            {
                DataRow row = IOConfig.Bits.Rows[i];
                try
                {
                    int pos = int.Parse(row["Pos"].ToString());
                    string name = row["Name"].ToString();
                    string text = row["Text"].ToString();
                    string parent = row["Parent"].ToString();
                    string datatype = row["DataType"].ToString().ToUpper();
                    PLC_IO_DATA_TYPE io_dat;
                    name = RemoveSpecialChar(name);
                    PLC_Cell parentCell = ((PLC_Cell)plcIO[parent]);
                    parentCell.Child_Bits.Add(name);
                    string description = text + ": the parent is " + parent + parentCell.Start_Addr.ToString() + " and the position is " + pos.ToString();
                    PLC_Cell bitCell;
                    switch (datatype)
                    {
                        case "BIT":
                            io_dat = PLC_IO_DATA_TYPE.Bit;
                            //myCreator[className].AddProperties(name, typeof(System.Boolean), true, true, description);
                            int offset = pos / 16;
                            int bitIndex = pos % 16;
                            bitCell = new PLC_Cell((parentCell.Start_Addr + offset), bitIndex, 1, PLC_Action_Flag.Write, parentCell.Type, PLC_IO_DATA_TYPE.Bit, parentCell.ID, string.Empty, parentCell.PLC);
                            break;
                        case "WORD":
                        default:
                            io_dat = PLC_IO_DATA_TYPE.Word;
                            //myCreator[className].AddProperties(name, typeof(System.Int32), true, true, description);
                            bitCell = new PLC_Cell((parentCell.Start_Addr + pos), 0, 1, PLC_Action_Flag.Write, parentCell.Type, PLC_IO_DATA_TYPE.Word, parentCell.ID, string.Empty, parentCell.PLC);
                            break;
                    }
                    PLC_Bit bit = new PLC_Bit(name, text, parent, pos, io_dat);
                    plcBits.Add(name, bit);
                    plcBitsCell.Add(name, bitCell);
                }
                catch (Exception ex)
                {
                    MessageBox.Show((string)row["Name"] + ex.Message);
                }
            }
        }
        private static void InitFunctions(string className)
        {
            //myCreator.AddClass(className);
            if (IOConfig.Functions == null)
            {
                return;
            }
            for (int i = 0; i < IOConfig.Functions.Rows.Count; i++)
            {
                DataRow row = IOConfig.Functions.Rows[i];
                if (string.IsNullOrEmpty(row[0].ToString()))
                    continue;
                string name = row["Name"].ToString();
                string text = row["Action"].ToString();
                PLC_Func bit = new PLC_Func(name, text);
                plcFuncs.Add(name, bit);
                //myCreator[className].AddProperties(name, typeof(System.Boolean), false, true, text);

                string[] acts = text.Split(new char[] { '/' }, 10000, StringSplitOptions.RemoveEmptyEntries);
                bit.Bits = new string[acts.Length];
                int j = 0;
                foreach (string var in acts)
                {
                    //string[] one = var.Split(new char[] { ':' }, 255, StringSplitOptions.RemoveEmptyEntries);
                    //one[0] = RemoveSpecialChar(one[0]);//added for script support)
                    //bit.Bits.Add(one[0], one[1]);
                    bit.Bits[j] = (var);
                    j++;
                }
            }

        }
        private static void AddScanPortsProperty(RefrenceTagGroupCreator myClass, string name, PLC_Cell cell)
        {
            string decription = string.Empty;
            switch (cell.Type)
            {
                case PLC_IO_Flag.CIO:
                    decription = "Address:CIO." + cell.Port_Addr + "." + cell.Bit_Index + " Count:" + cell.Data_Len.ToString()
                        + " ReadMode:" + cell.ReadMode;
                    break;
                case PLC_IO_Flag.DM:
                    decription = "Address:DM." + cell.Port_Addr + "." + cell.Bit_Index + " Count:" + cell.Data_Len.ToString()
                        + " ReadMode:" + cell.ReadMode;
                    break;
                case PLC_IO_Flag.H:
                    decription = "Address:H." + cell.Port_Addr + "." + cell.Bit_Index + " Count:" + cell.Data_Len.ToString()
                        + " ReadMode:" + cell.ReadMode;
                    break;
                case PLC_IO_Flag.E:
                    decription = "Address:E." + cell.Port_Addr + "." + cell.Bit_Index + " Count:" + cell.Data_Len.ToString()
                        + " ReadMode:" + cell.ReadMode;
                    break;
                case PLC_IO_Flag.W:
                    decription = "Address:W." + cell.Port_Addr + "." + cell.Bit_Index + " Count:" + cell.Data_Len.ToString()
                        + " ReadMode:" + cell.ReadMode;
                    break;
                case PLC_IO_Flag.Unkown:
                    decription = "Address:Unkown." + cell.Port_Addr + "." + cell.Bit_Index + " Count:" + cell.Data_Len.ToString()
                        + " ReadMode:" + cell.ReadMode;
                    break;
            }
            Type myType;
            switch (cell.Data_Type)
            {
                case PLC_IO_DATA_TYPE.Bit:
                    if (cell.Data_Len == 1)
                    {
                        myType = typeof(PLCBoolCell);
                    }
                    else
                    {
                        throw new Exception("bit len can only be 1,wrong ioconfig.xls:" + cell.Name);
                    }
                    switch (cell.Action)
                    {
                        case PLC_Action_Flag.Both:
                            myClass.AddRefrence(name, myType, decription);
                            break;
                        case PLC_Action_Flag.Write:
                            myClass.AddRefrence(name, myType, decription);
                            break;
                        case PLC_Action_Flag.Read:
                            myClass.AddRefrence(name, myType, decription);
                            break;
                    }
                    break;
                case PLC_IO_DATA_TYPE.Word:
                    if (cell.Data_Len == 1)
                    {
                        myType = typeof(PLCIntCell);
                    }
                    else
                    {
                        myType = typeof(PLCIntArrayCell);
                    }
                    switch (cell.Action)
                    {
                        case PLC_Action_Flag.Both:
                            myClass.AddRefrence(name, myType, decription);
                            break;
                        case PLC_Action_Flag.Write:
                            myClass.AddRefrence(name, myType, decription);
                            break;
                        case PLC_Action_Flag.Read:
                            myClass.AddRefrence(name, myType, decription);
                            break;
                    }
                    break;
            }
        }

        private static void AddPCICardIOProperty(RefrenceTagGroupCreator myClass, string name, PCICardDIO cell)
        {
            string decription = string.Empty;
            switch (cell.Port_Type)
            {
                case PCICard_PORT_TYPE.Input:
                    decription = "Input." + cell.Start_Addr.ToString() + "." + cell.Bit_Address.ToString() + " Count:" + cell.Data_Len.ToString()
                        + " ReadMode:" + cell.ReadMode;
                    break;
                default:
                    decription = "Output." + cell.Start_Addr.ToString() + "." + cell.Bit_Address.ToString() + " Count:" + cell.Data_Len.ToString()
                        + " ReadMode:" + cell.ReadMode;
                    break;
            }
            Type myType;
            switch (cell.Data_Type)
            {
                case PCICard_DATA_TYPE.Bit:
                    if (cell.Data_Len == 1)
                    {
                        myType = typeof(PCICardBoolCell);
                    }
                    else
                    {
                        throw new Exception("bit len can only be 1,wrong ioconfig.xls:" + cell.Name);
                    }
                    myClass.AddRefrence(name, myType, decription);
                    break;
                case PCICard_DATA_TYPE.Byte:
                    if (cell.Data_Len == 1)
                    {
                        myType = typeof(PCICardByteCell);
                    }
                    else
                    {
                        myType = typeof(PCICardByteArrayCell);
                    }
                    myClass.AddRefrence(name, myType, decription);
                    break;
            }
        }
        public static string RemoveSpecialChar(string value)
        {
            value = value.Replace(" ", "_");
            value = value.Replace("-", "_");
            value = value.Replace(".", "_");
            value = value.Replace("*", "_");
            return value;
        }
    }
}
